package com.hp.team.bookstore.service.order;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hp.team.bookstore.dbaccess.dao.order.SalesOrderHibernateDAO;
import com.hp.team.bookstore.model.ICommonConstants;
import com.hp.team.bookstore.model.order.SOStatus;
import com.hp.team.bookstore.model.order.SalesOrder;
import com.hp.team.bookstore.service.exception.BadOperationException;
import com.hp.team.bookstore.service.order.common.Status;

@Service
public class SalesOrderService extends OrderService {

	@Autowired
	private SalesOrderHibernateDAO orderDAO;

	public SalesOrderService() {
		setOperationsFile("so_operations.xml");
	}

	private SOStatus getStatus(String status) {
		if (status != null & !status.isEmpty()) {
			return SOStatus.valueOf(status.toUpperCase().replace(" ", "_"));
		}

		return null;
	}

	protected String getCreatorRoleName() {
		return ICommonConstants.ROLE_RETAILER;
	}

	@Transactional
	public Map<SalesOrder, Set<SOStatus>> getOrdersMap(String role, String operation) throws BadOperationException {

		initOperation(role, operation);

		Map<SalesOrder, Set<SOStatus>> ordersMap = new TreeMap<SalesOrder, Set<SOStatus>>();
		for (String fromStatus : getCurrentStatusPaths().keySet()) {
			Set<SalesOrder> orders = getOrdersList(getStatus(fromStatus));
			ordersMap.putAll(constructOrdersMap(orders));
		}

		return ordersMap;
	}

	@Transactional
	public Map<SalesOrder, Set<SOStatus>> getOrdersMap(String status, long creatorId) {
		Set<SalesOrder> orders = getOrdersList(getStatus(status), creatorId);
		return constructOrdersMap(orders);
	}

	private Map<SalesOrder, Set<SOStatus>> constructOrdersMap(Set<SalesOrder> orders) {
		Map<SalesOrder, Set<SOStatus>> foundOrders = new TreeMap<SalesOrder, Set<SOStatus>>();

		for (String fromStatus : getCurrentStatusPaths().keySet()) {

			for (SalesOrder order : orders) {

				if (order.getStatus().toString().equalsIgnoreCase(fromStatus)) {
					Set<SOStatus> toStatusList = new TreeSet<SOStatus>();
					for (String toStatus : getCurrentStatusPaths().get(fromStatus)) {
						toStatusList.add(getStatus(toStatus));
					}
					foundOrders.put(order, toStatusList);
				}
			}
		}

		System.out.println("Found orders: " + foundOrders);
		return foundOrders;
	}

	private Set<SalesOrder> getOrdersList(SOStatus status) {
		SalesOrder exampleOrder = new SalesOrder();
		
		if (status != null) {
			exampleOrder.setStatus(status);
		}
		
		return new TreeSet<SalesOrder>(orderDAO.findByExample(exampleOrder));
	}

	private Set<SalesOrder> getOrdersList(SOStatus status, long creatorId) {
		
		SalesOrder exampleOrder = new SalesOrder();

		if (status != null) {
			exampleOrder.setStatus(status);
		}
		
		List<SalesOrder> orders = creatorId != -1 ? orderDAO.findByCreator(exampleOrder, creatorId) : orderDAO.findByExample(exampleOrder);

		return new TreeSet<SalesOrder>(orders);
	}

	public Map<SalesOrder, Set<SOStatus>> removeFromOrdersMap(Map<SalesOrder, Set<SOStatus>> orders, long orderId) {
		Map<SalesOrder, Set<SOStatus>> newOrdersMap = new TreeMap<SalesOrder, Set<SOStatus>>();

		for (Entry<SalesOrder, Set<SOStatus>> entry : orders.entrySet()) {
			if (entry.getKey().getId() != orderId) {
				newOrdersMap.put(entry.getKey(), entry.getValue());
			}
		}

		return newOrdersMap;
	}

	public SalesOrder getFromOrdersMap(Map<SalesOrder, Set<SOStatus>> orders, long orderId) {

		for (SalesOrder order : orders.keySet()) {
			if (order.getId() == orderId) {
				return order;
			}
		}

		return null;
	}

	public Set<SOStatus> getAllAllowedStatuses() {
		Set<SOStatus> statuses = new TreeSet<SOStatus>();

		for (Status status : getCurrentOperation().getStatuses()) {
			statuses.add(getStatus(status.getFrom()));
		}

		return statuses;
	}

	@Transactional
	public void changeStatus(long orderId, String fromStatus, String toStatus) {
		SalesOrder order = orderDAO.findById(orderId, true);

		if (order.getStatus().equals(getStatus(fromStatus))) {
			setStatus(order, getStatus(toStatus));
		}
	}

	private void setStatus(SalesOrder order, SOStatus status) {
		order.setStatus(status);
		orderDAO.makePersistent(order);
	}
	
	@Transactional
	public boolean addSalesOrder(SalesOrder order) {
		boolean done=false;
		SalesOrder so = orderDAO.makePersistent(order);
		if(so != null){
			done=true;
		}
		return done;
	}
}
